package com.yf.exam.modules.user.cert.job;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yf.exam.ability.job.service.JobService;
import com.yf.exam.modules.user.cert.entity.UserCert;
import com.yf.exam.modules.user.cert.service.UserCertService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;

/**
 * 证书生成失败重试定时任务
 * 场景一：失败重试机制
 * 定期扫描失败的证书生成任务，进行重试
 * 
 * @author system
 */
@Slf4j
@Component
public class CertRetryJob implements Job {

    @Autowired
    private UserCertService userCertService;

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        JobDetail detail = jobExecutionContext.getJobDetail();
        String name = detail.getKey().getName();
        String group = detail.getKey().getGroup();
        String data = String.valueOf(detail.getJobDataMap().get(JobService.TASK_DATA));

        log.info("++++++++++定时任务：证书生成失败重试");
        log.info("++++++++++jobName:{}", name);
        log.info("++++++++++jobGroup:{}", group);
        log.info("++++++++++taskData:{}", data);

        try {
            // 查询失败的证书记录（24小时内的失败记录）
            QueryWrapper<UserCert> wrapper = new QueryWrapper<>();
            wrapper.eq("status", UserCert.STATUS_FAILED)
                   .ge("update_time", new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000))
                   .orderByAsc("update_time");
            
            List<UserCert> failedCerts = userCertService.list(wrapper);
            
            if (failedCerts.isEmpty()) {
                log.info("没有需要重试的失败证书记录");
                return;
            }
            
            log.info("找到 {} 个失败的证书记录，开始重试", failedCerts.size());
            
            int retryCount = 0;
            int maxRetryPerBatch = 10; // 每批次最多重试10个
            
            for (UserCert failedCert : failedCerts) {
                if (retryCount >= maxRetryPerBatch) {
                    log.info("本批次已重试 {} 个证书，达到上限", maxRetryPerBatch);
                    break;
                }
                
                try {
                    log.info("重试生成证书：userId={}, examId={}, certId={}", 
                            failedCert.getUserId(), failedCert.getExamId(), failedCert.getCertId());
                    
                    // 调用手动生成证书方法进行重试
                    userCertService.manualGenerateCertificate(
                            failedCert.getUserId(), 
                            failedCert.getExamId(), 
                            failedCert.getCertId()
                    );
                    
                    retryCount++;
                    log.info("证书重试提交成功：userId={}", failedCert.getUserId());
                    
                } catch (Exception e) {
                    log.error("证书重试失败：userId={}, error={}", failedCert.getUserId(), e.getMessage());
                }
                
                // 避免过于频繁的重试，间隔1秒
                Thread.sleep(1000);
            }
            
            log.info("证书失败重试任务完成，本次重试了 {} 个证书", retryCount);
            
        } catch (Exception e) {
            log.error("证书失败重试任务执行异常", e);
            throw new JobExecutionException(e);
        }
    }
}